home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Source / GNU / libg++ / libiberty / strerror.c < prev    next >
C/C++ Source or Header  |  1994-02-15  |  21KB  |  820 lines

  1. /* Extended support for using errno values.
  2.    Copyright (C) 1992 Free Software Foundation, Inc.
  3.    Written by Fred Fish.  fnf@cygnus.com
  4.  
  5. This file is part of the libiberty library.
  6. Libiberty is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU Library General Public
  8. License as published by the Free Software Foundation; either
  9. version 2 of the License, or (at your option) any later version.
  10.  
  11. Libiberty is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14. Library General Public License for more details.
  15.  
  16. You should have received a copy of the GNU Library General Public
  17. License along with libiberty; see the file COPYING.LIB.  If
  18. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  19. Cambridge, MA 02139, USA.  */
  20.  
  21. #include "config.h"
  22.  
  23. #ifndef NEED_sys_errlist
  24. /* Note that errno.h (not sure what OS) or stdio.h (BSD 4.4, at least)
  25.    might declare sys_errlist in a way that the compiler might consider
  26.    incompatible with our later declaration, perhaps by using const
  27.    attributes.  So we hide the declaration in errno.h (if any) using a
  28.    macro. */
  29. #define sys_errlist sys_errlist__
  30. #endif
  31.  
  32. #include <stdio.h>
  33. #include <errno.h>
  34.  
  35. #ifndef NEED_sys_errlist
  36. #undef sys_errlist
  37. #endif
  38.  
  39. /*  Routines imported from standard C runtime libraries. */
  40.  
  41. #ifdef __STDC__
  42. #include <stddef.h>
  43. extern void *malloc (size_t size);                /* 4.10.3.3 */
  44. extern void *memset (void *s, int c, size_t n);            /* 4.11.6.1 */
  45. #else    /* !__STDC__ */
  46. #ifndef const
  47. #define const
  48. #endif
  49. extern char *malloc ();        /* Standard memory allocater */
  50. extern char *memset ();
  51. #endif    /* __STDC__ */
  52.  
  53. #ifndef MAX
  54. #  define MAX(a,b) ((a) > (b) ? (a) : (b))
  55. #endif
  56.  
  57. /* Translation table for errno values.  See intro(2) in most UNIX systems
  58.    Programmers Reference Manuals.
  59.  
  60.    Note that this table is generally only accessed when it is used at runtime
  61.    to initialize errno name and message tables that are indexed by errno
  62.    value.
  63.  
  64.    Not all of these errnos will exist on all systems.  This table is the only
  65.    thing that should have to be updated as new error numbers are introduced.
  66.    It's sort of ugly, but at least its portable. */
  67.  
  68. struct error_info
  69. {
  70.   int value;        /* The numeric value from <errno.h> */
  71.   char *name;        /* The equivalent symbolic value */
  72. #ifdef NEED_sys_errlist
  73.   char *msg;        /* Short message about this value */
  74. #endif
  75. };
  76.  
  77. #ifdef NEED_sys_errlist
  78. #   define ENTRY(value, name, msg)    {value, name, msg}
  79. #else
  80. #   define ENTRY(value, name, msg)    {value, name}
  81. #endif
  82.  
  83. static const struct error_info error_table[] =
  84. {
  85. #if defined (EPERM)
  86.   ENTRY(EPERM, "EPERM", "Not owner"),
  87. #endif
  88. #if defined (ENOENT)
  89.   ENTRY(ENOENT, "ENOENT", "No such file or directory"),
  90. #endif
  91. #if defined (ESRCH)
  92.   ENTRY(ESRCH, "ESRCH", "No such process"),
  93. #endif
  94. #if defined (EINTR)
  95.   ENTRY(EINTR, "EINTR", "Interrupted system call"),
  96. #endif
  97. #if defined (EIO)
  98.   ENTRY(EIO, "EIO", "I/O error"),
  99. #endif
  100. #if defined (ENXIO)
  101.   ENTRY(ENXIO, "ENXIO", "No such device or address"),
  102. #endif
  103. #if defined (E2BIG)
  104.   ENTRY(E2BIG, "E2BIG", "Arg list too long"),
  105. #endif
  106. #if defined (ENOEXEC)
  107.   ENTRY(ENOEXEC, "ENOEXEC", "Exec format error"),
  108. #endif
  109. #if defined (EBADF)
  110.   ENTRY(EBADF, "EBADF", "Bad file number"),
  111. #endif
  112. #if defined (ECHILD)
  113.   ENTRY(ECHILD, "ECHILD", "No child processes"),
  114. #endif
  115. #if defined (EWOULDBLOCK)    /* Put before EAGAIN, sometimes aliased */
  116.   ENTRY(EWOULDBLOCK, "EWOULDBLOCK", "Operation would block"),
  117. #endif
  118. #if defined (EAGAIN)
  119.   ENTRY(EAGAIN, "EAGAIN", "No more processes"),
  120. #endif
  121. #if defined (ENOMEM)
  122.   ENTRY(ENOMEM, "ENOMEM", "Not enough space"),
  123. #endif
  124. #if defined (EACCES)
  125.   ENTRY(EACCES, "EACCES", "Permission denied"),
  126. #endif
  127. #if defined (EFAULT)
  128.   ENTRY(EFAULT, "EFAULT", "Bad address"),
  129. #endif
  130. #if defined (ENOTBLK)
  131.   ENTRY(ENOTBLK, "ENOTBLK", "Block device required"),
  132. #endif
  133. #if defined (EBUSY)
  134.   ENTRY(EBUSY, "EBUSY", "Device busy"),
  135. #endif
  136. #if defined (EEXIST)
  137.   ENTRY(EEXIST, "EEXIST", "File exists"),
  138. #endif
  139. #if defined (EXDEV)
  140.   ENTRY(EXDEV, "EXDEV", "Cross-device link"),
  141. #endif
  142. #if defined (ENODEV)
  143.   ENTRY(ENODEV, "ENODEV", "No such device"),
  144. #endif
  145. #if defined (ENOTDIR)
  146.   ENTRY(ENOTDIR, "ENOTDIR", "Not a directory"),
  147. #endif
  148. #if defined (EISDIR)
  149.   ENTRY(EISDIR, "EISDIR", "Is a directory"),
  150. #endif
  151. #if defined (EINVAL)
  152.   ENTRY(EINVAL, "EINVAL", "Invalid argument"),
  153. #endif
  154. #if defined (ENFILE)
  155.   ENTRY(ENFILE, "ENFILE", "File table overflow"),
  156. #endif
  157. #if defined (EMFILE)
  158.   ENTRY(EMFILE, "EMFILE", "Too many open files"),
  159. #endif
  160. #if defined (ENOTTY)
  161.   ENTRY(ENOTTY, "ENOTTY", "Not a typewriter"),
  162. #endif
  163. #if defined (ETXTBSY)
  164.   ENTRY(ETXTBSY, "ETXTBSY", "Text file busy"),
  165. #endif
  166. #if defined (EFBIG)
  167.   ENTRY(EFBIG, "EFBIG", "File too large"),
  168. #endif
  169. #if defined (ENOSPC)
  170.   ENTRY(ENOSPC, "ENOSPC", "No space left on device"),
  171. #endif
  172. #if defined (ESPIPE)
  173.   ENTRY(ESPIPE, "ESPIPE", "Illegal seek"),
  174. #endif
  175. #if defined (EROFS)
  176.   ENTRY(EROFS, "EROFS", "Read-only file system"),
  177. #endif
  178. #if defined (EMLINK)
  179.   ENTRY(EMLINK, "EMLINK", "Too many links"),
  180. #endif
  181. #if defined (EPIPE)
  182.   ENTRY(EPIPE, "EPIPE", "Broken pipe"),
  183. #endif
  184. #if defined (EDOM)
  185.   ENTRY(EDOM, "EDOM", "Math argument out of domain of func"),
  186. #endif
  187. #if defined (ERANGE)
  188.   ENTRY(ERANGE, "ERANGE", "Math result not representable"),
  189. #endif
  190. #if defined (ENOMSG)
  191.   ENTRY(ENOMSG, "ENOMSG", "No message of desired type"),
  192. #endif
  193. #if defined (EIDRM)
  194.   ENTRY(EIDRM, "EIDRM", "Identifier removed"),
  195. #endif
  196. #if defined (ECHRNG)
  197.   ENTRY(ECHRNG, "ECHRNG", "Channel number out of range"),
  198. #endif
  199. #if defined (EL2NSYNC)
  200.   ENTRY(EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized"),
  201. #endif
  202. #if defined (EL3HLT)
  203.   ENTRY(EL3HLT, "EL3HLT", "Level 3 halted"),
  204. #endif
  205. #if defined (EL3RST)
  206.   ENTRY(EL3RST, "EL3RST", "Level 3 reset"),
  207. #endif
  208. #if defined (ELNRNG)
  209.   ENTRY(ELNRNG, "ELNRNG", "Link number out of range"),
  210. #endif
  211. #if defined (EUNATCH)
  212.   ENTRY(EUNATCH, "EUNATCH", "Protocol driver not attached"),
  213. #endif
  214. #if defined (ENOCSI)
  215.   ENTRY(ENOCSI, "ENOCSI", "No CSI structure available"),
  216. #endif
  217. #if defined (EL2HLT)
  218.   ENTRY(EL2HLT, "EL2HLT", "Level 2 halted"),
  219. #endif
  220. #if defined (EDEADLK)
  221.   ENTRY(EDEADLK, "EDEADLK", "Deadlock condition"),
  222. #endif
  223. #if defined (ENOLCK)
  224.   ENTRY(ENOLCK, "ENOLCK", "No record locks available"),
  225. #endif
  226. #if defined (EBADE)
  227.   ENTRY(EBADE, "EBADE", "Invalid exchange"),
  228. #endif
  229. #if defined (EBADR)
  230.   ENTRY(EBADR, "EBADR", "Invalid request descriptor"),
  231. #endif
  232. #if defined (EXFULL)
  233.   ENTRY(EXFULL, "EXFULL", "Exchange full"),
  234. #endif
  235. #if defined (ENOANO)
  236.   ENTRY(ENOANO, "ENOANO", "No anode"),
  237. #endif
  238. #if defined (EBADRQC)
  239.   ENTRY(EBADRQC, "EBADRQC", "Invalid request code"),
  240. #endif
  241. #if defined (EBADSLT)
  242.   ENTRY(EBADSLT, "EBADSLT", "Invalid slot"),
  243. #endif
  244. #if defined (EDEADLOCK)
  245.   ENTRY(EDEADLOCK, "EDEADLOCK", "File locking deadlock error"),
  246. #endif
  247. #if defined (EBFONT)
  248.   ENTRY(EBFONT, "EBFONT", "Bad font file format"),
  249. #endif
  250. #if defined (ENOSTR)
  251.   ENTRY(ENOSTR, "ENOSTR", "Device not a stream"),
  252. #endif
  253. #if defined (ENODATA)
  254.   ENTRY(ENODATA, "ENODATA", "No data available"),
  255. #endif
  256. #if defined (ETIME)
  257.   ENTRY(ETIME, "ETIME", "Timer expired"),
  258. #endif
  259. #if defined (ENOSR)
  260.   ENTRY(ENOSR, "ENOSR", "Out of streams resources"),
  261. #endif
  262. #if defined (ENONET)
  263.   ENTRY(ENONET, "ENONET", "Machine is not on the network"),
  264. #endif
  265. #if defined (ENOPKG)
  266.   ENTRY(ENOPKG, "ENOPKG", "Package not installed"),
  267. #endif
  268. #if defined (EREMOTE)
  269.   ENTRY(EREMOTE, "EREMOTE", "Object is remote"),
  270. #endif
  271. #if defined (ENOLINK)
  272.   ENTRY(ENOLINK, "ENOLINK", "Link has been severed"),
  273. #endif
  274. #if defined (EADV)
  275.   ENTRY(EADV, "EADV", "Advertise error"),
  276. #endif
  277. #if defined (ESRMNT)
  278.   ENTRY(ESRMNT, "ESRMNT", "Srmount error"),
  279. #endif
  280. #if defined (ECOMM)
  281.   ENTRY(ECOMM, "ECOMM", "Communication error on send"),
  282. #endif
  283. #if defined (EPROTO)
  284.   ENTRY(EPROTO, "EPROTO", "Protocol error"),
  285. #endif
  286. #if defined (EMULTIHOP)
  287.   ENTRY(EMULTIHOP, "EMULTIHOP", "Multihop attempted"),
  288. #endif
  289. #if defined (EDOTDOT)
  290.   ENTRY(EDOTDOT, "EDOTDOT", "RFS specific error"),
  291. #endif
  292. #if defined (EBADMSG)
  293.   ENTRY(EBADMSG, "EBADMSG", "Not a data message"),
  294. #endif
  295. #if defined (ENAMETOOLONG)
  296.   ENTRY(ENAMETOOLONG, "ENAMETOOLONG", "File name too long"),
  297. #endif
  298. #if defined (EOVERFLOW)
  299.   ENTRY(EOVERFLOW, "EOVERFLOW", "Value too large for defined data type"),
  300. #endif
  301. #if defined (ENOTUNIQ)
  302.   ENTRY(ENOTUNIQ, "ENOTUNIQ", "Name not unique on network"),
  303. #endif
  304. #if defined (EBADFD)
  305.   ENTRY(EBADFD, "EBADFD", "File descriptor in bad state"),
  306. #endif
  307. #if defined (EREMCHG)
  308.   ENTRY(EREMCHG, "EREMCHG", "Remote address changed"),
  309. #endif
  310. #if defined (ELIBACC)
  311.   ENTRY(ELIBACC, "ELIBACC", "Can not access a needed shared library"),
  312. #endif
  313. #if defined (ELIBBAD)
  314.   ENTRY(ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library"),
  315. #endif
  316. #if defined (ELIBSCN)
  317.   ENTRY(ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted"),
  318. #endif
  319. #if defined (ELIBMAX)
  320.   ENTRY(ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries"),
  321. #endif
  322. #if defined (ELIBEXEC)
  323.   ENTRY(ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly"),
  324. #endif
  325. #if defined (EILSEQ)
  326.   ENTRY(EILSEQ, "EILSEQ", "Illegal byte sequence"),
  327. #endif
  328. #if defined (ENOSYS)
  329.   ENTRY(ENOSYS, "ENOSYS", "Operation not applicable"),
  330. #endif
  331. #if defined (ELOOP)
  332.   ENTRY(ELOOP, "ELOOP", "Too many symbolic links encountered"),
  333. #endif
  334. #if defined (ERESTART)
  335.   ENTRY(ERESTART, "ERESTART", "Interrupted system call should be restarted"),
  336. #endif
  337. #if defined (ESTRPIPE)
  338.   ENTRY(ESTRPIPE, "ESTRPIPE", "Streams pipe error"),
  339. #endif
  340. #if defined (ENOTEMPTY)
  341.   ENTRY(ENOTEMPTY, "ENOTEMPTY", "Directory not empty"),
  342. #endif
  343. #if defined (EUSERS)
  344.   ENTRY(EUSERS, "EUSERS", "Too many users"),
  345. #endif
  346. #if defined (ENOTSOCK)
  347.   ENTRY(ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket"),
  348. #endif
  349. #if defined (EDESTADDRREQ)
  350.   ENTRY(EDESTADDRREQ, "EDESTADDRREQ", "Destination address required"),
  351. #endif
  352. #if defined (EMSGSIZE)
  353.   ENTRY(EMSGSIZE, "EMSGSIZE", "Message too long"),
  354. #endif
  355. #if defined (EPROTOTYPE)
  356.   ENTRY(EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket"),
  357. #endif
  358. #if defined (ENOPROTOOPT)
  359.   ENTRY(ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available"),
  360. #endif
  361. #if defined (EPROTONOSUPPORT)
  362.   ENTRY(EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported"),
  363. #endif
  364. #if defined (ESOCKTNOSUPPORT)
  365.   ENTRY(ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported"),
  366. #endif
  367. #if defined (EOPNOTSUPP)
  368.   ENTRY(EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint"),
  369. #endif
  370. #if defined (EPFNOSUPPORT)
  371.   ENTRY(EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported"),
  372. #endif
  373. #if defined (EAFNOSUPPORT)
  374.   ENTRY(EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol"),
  375. #endif
  376. #if defined (EADDRINUSE)
  377.   ENTRY(EADDRINUSE, "EADDRINUSE", "Address already in use"),
  378. #endif
  379. #if defined (EADDRNOTAVAIL)
  380.   ENTRY(EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address"),
  381. #endif
  382. #if defined (ENETDOWN)
  383.   ENTRY(ENETDOWN, "ENETDOWN", "Network is down"),
  384. #endif
  385. #if defined (ENETUNREACH)
  386.   ENTRY(ENETUNREACH, "ENETUNREACH", "Network is unreachable"),
  387. #endif
  388. #if defined (ENETRESET)
  389.   ENTRY(ENETRESET, "ENETRESET", "Network dropped connection because of reset"),
  390. #endif
  391. #if defined (ECONNABORTED)
  392.   ENTRY(ECONNABORTED, "ECONNABORTED", "Software caused connection abort"),
  393. #endif
  394. #if defined (ECONNRESET)
  395.   ENTRY(ECONNRESET, "ECONNRESET", "Connection reset by peer"),
  396. #endif
  397. #if defined (ENOBUFS)
  398.   ENTRY(ENOBUFS, "ENOBUFS", "No buffer space available"),
  399. #endif
  400. #if defined (EISCONN)
  401.   ENTRY(EISCONN, "EISCONN", "Transport endpoint is already connected"),
  402. #endif
  403. #if defined (ENOTCONN)
  404.   ENTRY(ENOTCONN, "ENOTCONN", "Transport endpoint is not connected"),
  405. #endif
  406. #if defined (ESHUTDOWN)
  407.   ENTRY(ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown"),
  408. #endif
  409. #if defined (ETOOMANYREFS)
  410.   ENTRY(ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice"),
  411. #endif
  412. #if defined (ETIMEDOUT)
  413.   ENTRY(ETIMEDOUT, "ETIMEDOUT", "Connection timed out"),
  414. #endif
  415. #if defined (ECONNREFUSED)
  416.   ENTRY(ECONNREFUSED, "ECONNREFUSED", "Connection refused"),
  417. #endif
  418. #if defined (EHOSTDOWN)
  419.   ENTRY(EHOSTDOWN, "EHOSTDOWN", "Host is down"),
  420. #endif
  421. #if defined (EHOSTUNREACH)
  422.   ENTRY(EHOSTUNREACH, "EHOSTUNREACH", "No route to host"),
  423. #endif
  424. #if defined (EALREADY)
  425.   ENTRY(EALREADY, "EALREADY", "Operation already in progress"),
  426. #endif
  427. #if defined (EINPROGRESS)
  428.   ENTRY(EINPROGRESS, "EINPROGRESS", "Operation now in progress"),
  429. #endif
  430. #if defined (ESTALE)
  431.   ENTRY(ESTALE, "ESTALE", "Stale NFS file handle"),
  432. #endif
  433. #if defined (EUCLEAN)
  434.   ENTRY(EUCLEAN, "EUCLEAN", "Structure needs cleaning"),
  435. #endif
  436. #if defined (ENOTNAM)
  437.   ENTRY(ENOTNAM, "ENOTNAM", "Not a XENIX named type file"),
  438. #endif
  439. #if defined (ENAVAIL)
  440.   ENTRY(ENAVAIL, "ENAVAIL", "No XENIX semaphores available"),
  441. #endif
  442. #if defined (EISNAM)
  443.   ENTRY(EISNAM, "EISNAM", "Is a named type file"),
  444. #endif
  445. #if defined (EREMOTEIO)
  446.   ENTRY(EREMOTEIO, "EREMOTEIO", "Remote I/O error"),
  447. #endif
  448.   ENTRY(0, NULL, NULL)
  449. };
  450.  
  451. /* Translation table allocated and initialized at runtime.  Indexed by the
  452.    errno value to find the equivalent symbolic value. */
  453.  
  454. static char **error_names;
  455. static int num_error_names = 0;
  456.  
  457. /* Translation table allocated and initialized at runtime, if it does not
  458.    already exist in the host environment.  Indexed by the errno value to find
  459.    the descriptive string.
  460.  
  461.    We don't export it for use in other modules because even though it has the
  462.    same name, it differs from other implementations in that it is dynamically
  463.    initialized rather than statically initialized. */
  464.  
  465. #ifdef NEED_sys_errlist
  466.  
  467. static int sys_nerr;
  468. static char **sys_errlist;
  469.  
  470. #else
  471.  
  472. extern int sys_nerr;
  473. extern char *sys_errlist[];
  474.  
  475. #endif
  476.  
  477.  
  478. /*
  479.  
  480. NAME
  481.  
  482.     init_error_tables -- initialize the name and message tables
  483.  
  484. SYNOPSIS
  485.  
  486.     static void init_error_tables ();
  487.  
  488. DESCRIPTION
  489.  
  490.     Using the error_table, which is initialized at compile time, generate
  491.     the error_names and the sys_errlist (if needed) tables, which are
  492.     indexed at runtime by a specific errno value.
  493.  
  494. BUGS
  495.  
  496.     The initialization of the tables may fail under low memory conditions,
  497.     in which case we don't do anything particularly useful, but we don't
  498.     bomb either.  Who knows, it might succeed at a later point if we free
  499.     some memory in the meantime.  In any case, the other routines know
  500.     how to deal with lack of a table after trying to initialize it.  This
  501.     may or may not be considered to be a bug, that we don't specifically
  502.     warn about this particular failure mode.
  503.  
  504. */
  505.  
  506. static void
  507. init_error_tables ()
  508. {
  509.   const struct error_info *eip;
  510.   int nbytes;
  511.  
  512.   /* If we haven't already scanned the error_table once to find the maximum
  513.      errno value, then go find it now. */
  514.  
  515.   if (num_error_names == 0)
  516.     {
  517.       for (eip = error_table; eip -> name != NULL; eip++)
  518.     {
  519.       if (eip -> value >= num_error_names)
  520.         {
  521.           num_error_names = eip -> value + 1;
  522.         }
  523.     }
  524.     }
  525.  
  526.   /* Now attempt to allocate the error_names table, zero it out, and then
  527.      initialize it from the statically initialized error_table. */
  528.  
  529.   if (error_names == NULL)
  530.     {
  531.       nbytes = num_error_names * sizeof (char *);
  532.       if ((error_names = (char **) malloc (nbytes)) != NULL)
  533.     {
  534.       memset (error_names, 0, nbytes);
  535.       for (eip = error_table; eip -> name != NULL; eip++)
  536.         {
  537.           error_names[eip -> value] = eip -> name;
  538.         }
  539.     }
  540.     }
  541.  
  542. #ifdef NEED_sys_errlist
  543.  
  544.   /* Now attempt to allocate the sys_errlist table, zero it out, and then
  545.      initialize it from the statically initialized error_table. */
  546.  
  547.   if (sys_errlist == NULL)
  548.     {
  549.       nbytes = num_error_names * sizeof (char *);
  550.       if ((sys_errlist = (char **) malloc (nbytes)) != NULL)
  551.     {
  552.       memset (sys_errlist, 0, nbytes);
  553.       sys_nerr = num_error_names;
  554.       for (eip = error_table; eip -> name != NULL; eip++)
  555.         {
  556.           sys_errlist[eip -> value] = eip -> msg;
  557.         }
  558.     }
  559.     }
  560.  
  561. #endif
  562.  
  563. }
  564.  
  565. /*
  566.  
  567. NAME
  568.  
  569.     errno_max -- return the max errno value
  570.  
  571. SYNOPSIS
  572.  
  573.     int errno_max ();
  574.  
  575. DESCRIPTION
  576.  
  577.     Returns the maximum errno value for which a corresponding symbolic
  578.     name or message is available.  Note that in the case where
  579.     we use the sys_errlist supplied by the system, it is possible for
  580.     there to be more symbolic names than messages, or vice versa.
  581.     In fact, the manual page for perror(3C) explicitly warns that one
  582.     should check the size of the table (sys_nerr) before indexing it,
  583.     since new error codes may be added to the system before they are
  584.     added to the table.  Thus sys_nerr might be smaller than value
  585.     implied by the largest errno value defined in <errno.h>.
  586.  
  587.     We return the maximum value that can be used to obtain a meaningful
  588.     symbolic name or message.
  589.  
  590. */
  591.  
  592. int
  593. errno_max ()
  594. {
  595.   int maxsize;
  596.  
  597.   if (error_names == NULL)
  598.     {
  599.       init_error_tables ();
  600.     }
  601.   maxsize = MAX (sys_nerr, num_error_names);
  602.   return (maxsize - 1);
  603. }
  604.  
  605. #ifdef NEED_strerror
  606.  
  607. /*
  608.  
  609. NAME
  610.  
  611.     strerror -- map an error number to an error message string
  612.  
  613. SYNOPSIS
  614.  
  615.     char *strerror (int errnoval)
  616.  
  617. DESCRIPTION
  618.  
  619.     Maps an errno number to an error message string, the contents of
  620.     which are implementation defined.  On systems which have the external
  621.     variables sys_nerr and sys_errlist, these strings will be the same
  622.     as the ones used by perror().
  623.  
  624.     If the supplied error number is within the valid range of indices
  625.     for the sys_errlist, but no message is available for the particular
  626.     error number, then returns the string "Error NUM", where NUM is the
  627.     error number.
  628.  
  629.     If the supplied error number is not a valid index into sys_errlist,
  630.     returns NULL.
  631.  
  632.     The returned string is only guaranteed to be valid only until the
  633.     next call to strerror.
  634.  
  635. */
  636.  
  637. char *
  638. strerror (errnoval)
  639.   int errnoval;
  640. {
  641.   char *msg;
  642.   static char buf[32];
  643.  
  644. #ifdef NEED_sys_errlist
  645.  
  646.   if (error_names == NULL)
  647.     {
  648.       init_error_tables ();
  649.     }
  650.  
  651. #endif
  652.  
  653.   if ((errnoval < 0) || (errnoval >= sys_nerr))
  654.     {
  655.       /* Out of range, just return NULL */
  656.       msg = NULL;
  657.     }
  658.   else if ((sys_errlist == NULL) || (sys_errlist[errnoval] == NULL))
  659.     {
  660.       /* In range, but no sys_errlist or no entry at this index. */
  661.       sprintf (buf, "Error %d", errnoval);
  662.       msg = buf;
  663.     }
  664.   else
  665.     {
  666.       /* In range, and a valid message.  Just return the message. */
  667.       msg = sys_errlist[errnoval];
  668.     }
  669.   
  670.   return (msg);
  671. }
  672.  
  673. #endif    /* NEED_strerror */
  674.  
  675.  
  676. /*
  677.  
  678. NAME
  679.  
  680.     strerrno -- map an error number to a symbolic name string
  681.  
  682. SYNOPSIS
  683.  
  684.     char *strerrno (int errnoval)
  685.  
  686. DESCRIPTION
  687.  
  688.     Given an error number returned from a system call (typically
  689.     returned in errno), returns a pointer to a string containing the
  690.     symbolic name of that error number, as found in <errno.h>.
  691.  
  692.     If the supplied error number is within the valid range of indices
  693.     for symbolic names, but no name is available for the particular
  694.     error number, then returns the string "Error NUM", where NUM is
  695.     the error number.
  696.  
  697.     If the supplied error number is not within the range of valid
  698.     indices, then returns NULL.
  699.  
  700. BUGS
  701.  
  702.     The contents of the location pointed to are only guaranteed to be
  703.     valid until the next call to strerrno.
  704.  
  705. */
  706.  
  707. char *
  708. strerrno (errnoval)
  709.   int errnoval;
  710. {
  711.   char *name;
  712.   static char buf[32];
  713.  
  714.   if (error_names == NULL)
  715.     {
  716.       init_error_tables ();
  717.     }
  718.  
  719.   if ((errnoval < 0) || (errnoval >= num_error_names))
  720.     {
  721.       /* Out of range, just return NULL */
  722.       name = NULL;
  723.     }
  724.   else if ((error_names == NULL) || (error_names[errnoval] == NULL))
  725.     {
  726.       /* In range, but no error_names or no entry at this index. */
  727.       sprintf (buf, "Error %d", errnoval);
  728.       name = buf;
  729.     }
  730.   else
  731.     {
  732.       /* In range, and a valid name.  Just return the name. */
  733.       name = error_names[errnoval];
  734.     }
  735.  
  736.   return (name);
  737. }
  738.  
  739. /*
  740.  
  741. NAME
  742.  
  743.     strtoerrno -- map a symbolic errno name to a numeric value
  744.  
  745. SYNOPSIS
  746.  
  747.     int strtoerrno (char *name)
  748.  
  749. DESCRIPTION
  750.  
  751.     Given the symbolic name of a error number, map it to an errno value.
  752.     If no translation is found, returns 0.
  753.  
  754. */
  755.  
  756. int
  757. strtoerrno (name)
  758.   char *name;
  759. {
  760.   int errnoval = 0;
  761.  
  762.   if (name != NULL)
  763.     {
  764.       if (error_names == NULL)
  765.     {
  766.       init_error_tables ();
  767.     }
  768.       for (errnoval = 0; errnoval < num_error_names; errnoval++)
  769.     {
  770.       if ((error_names[errnoval] != NULL) &&
  771.           (strcmp (name, error_names[errnoval]) == 0))
  772.         {
  773.           break;
  774.         }
  775.     }
  776.       if (errnoval == num_error_names)
  777.     {
  778.       errnoval = 0;
  779.     }
  780.     }
  781.   return (errnoval);
  782. }
  783.  
  784.  
  785. /* A simple little main that does nothing but print all the errno translations
  786.    if MAIN is defined and this file is compiled and linked. */
  787.  
  788. #ifdef MAIN
  789.  
  790. main ()
  791. {
  792.   int errn;
  793.   int errnmax;
  794.   char *name;
  795.   char *msg;
  796.   char *strerrno ();
  797.   char *strerror ();
  798.  
  799.   errnmax = errno_max ();
  800.   printf ("%d entries in names table.\n", num_error_names);
  801.   printf ("%d entries in messages table.\n", sys_nerr);
  802.   printf ("%d is max useful index.\n", errnmax);
  803.  
  804.   /* Keep printing values until we get to the end of *both* tables, not
  805.      *either* table.  Note that knowing the maximum useful index does *not*
  806.      relieve us of the responsibility of testing the return pointer for
  807.      NULL. */
  808.  
  809.   for (errn = 0; errn <= errnmax; errn++)
  810.     {
  811.       name = strerrno (errn);
  812.       name = (name == NULL) ? "<NULL>" : name;
  813.       msg = strerror (errn);
  814.       msg = (msg == NULL) ? "<NULL>" : msg;
  815.       printf ("%-4d%-18s%s\n", errn, name, msg);
  816.     }
  817. }
  818.  
  819. #endif
  820.